package com.nidu.demo.mail.executor.command;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Validator;
import com.alibaba.cola.dto.Response;
import com.nidu.demo.common.enums.MailSendStatusEnum;
import com.nidu.demo.mail.ability.MailAccountDomainService;
import com.nidu.demo.mail.ability.MailTemplateDomainService;
import com.nidu.demo.mail.dto.MailSendCmd;
import com.nidu.demo.mail.model.MailSendEvent;
import com.nidu.demo.mail.gateway.MailLogGateway;
import com.nidu.demo.mail.model.MailAccount;
import com.nidu.demo.mail.model.MailLog;
import com.nidu.demo.mail.model.MailTemplate;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;

/**
 * 邮件发送命令执行器
 *
 * @author auto
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class MailSendCmdExe {

    private final MailLogGateway mailLogGateway;
    private final MailTemplateDomainService mailTemplateDomainService;
    private final MailAccountDomainService mailAccountDomainService;
    private final ApplicationEventPublisher eventPublisher;

    public Response execute(Long userId, Integer userType, MailSendCmd cmd) {
        // 1.1 校验邮箱模版是否合法
        MailTemplate template = mailTemplateDomainService.validateMailTemplate(cmd.getTemplateCode());
        // 1.2 校验邮箱账号是否合法
        MailAccount account = mailAccountDomainService.validateMailAccount(template.getAccountId());
        // 1.3 校验邮件参数是否缺失
        mailTemplateDomainService.validateTemplateParams(template, cmd.getTemplateParams());

        // 2. 组装邮箱
        Collection<String> toMailSet = new LinkedHashSet<>();
        Collection<String> ccMailSet = new LinkedHashSet<>();
        Collection<String> bccMailSet = new LinkedHashSet<>();
        if (CollUtil.isNotEmpty(cmd.getToMails())) {
            cmd.getToMails().stream().filter(Validator::isEmail).forEach(toMailSet::add);
        }
        if (CollUtil.isNotEmpty(cmd.getCcMails())) {
            cmd.getCcMails().stream().filter(Validator::isEmail).forEach(ccMailSet::add);
        }
        if (CollUtil.isNotEmpty(cmd.getBccMails())) {
            cmd.getBccMails().stream().filter(Validator::isEmail).forEach(bccMailSet::add);
        }

        // 创建发送日志。如果模板被禁用，则不发送短信，只记录日志
        String title = template.formatTemplateTitle(template.getTemplateTitle(), cmd.getTemplateParams());
        String content = template.formatTemplateContent(template.getTemplateContent(), cmd.getTemplateParams());

        MailLog mailLog = MailLog.create(userId, userType, new ArrayList<>(toMailSet), new ArrayList<>(ccMailSet), new ArrayList<>(bccMailSet), account.getId(), account.getMail(),
                template.getId(), template.getTemplateCode(), template.getTemplateNickname(), title, content, cmd.getTemplateParams());
        
        // 设置初始发送状态
        mailLog.setSendStatus(MailSendStatusEnum.INIT.getValue());
        
        // 保存邮件日志
        MailLog savedMailLog = mailLogGateway.create(mailLog);
        
        // 发布邮件发送事件，异步处理
        eventPublisher.publishEvent(new MailSendEvent(this, savedMailLog.getId()));
        
        return Response.buildSuccess();
    }

    public Response execute(Long id) {
        MailLog mailLog = mailLogGateway.getById(id);
        mailLog.setId(null);
        // 设置初始发送状态
        mailLog.setSendStatus(MailSendStatusEnum.INIT.getValue());
        
        // 保存邮件日志
        MailLog savedMailLog = mailLogGateway.create(mailLog);
        
        // 发布邮件发送事件，异步处理
        eventPublisher.publishEvent(new MailSendEvent(this, savedMailLog.getId()));
        
        return Response.buildSuccess();
    }

}
